package com.dtp.core.notify.alarm;

import com.dtp.common.entity.NotifyItem;
import com.dtp.common.em.NotifyItemEnum;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import org.apache.commons.lang3.StringUtils;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;

/**
 * 报警限制器（用来限制某个时间段内只能发送一次警告）
 *
 * @author yanhom
 * @since 1.0.0
 *
 * @remark muse
 */
public class AlarmLimiter {

    private static final Map<String, Cache<String, String>> ALARM_LIMITER = new ConcurrentHashMap<>(); // 报警限制缓存

    private AlarmLimiter() {}

    /** 针对某个线程池的通知项，来初始化报警限制器 */
    public static void initAlarmLimiter(String threadPoolName, NotifyItem notifyItem) {
        // 如果是【CHANGE：配置变更通知类型】，则不做处理
        if (NotifyItemEnum.CHANGE.getValue().equalsIgnoreCase(notifyItem.getType())) return;

        // 生成key，放入缓存中
        String key = genKey(threadPoolName, notifyItem.getType());

        // 创建缓存，如果向缓存中写入内容，则会在interval秒内有效，目的是在interval的间隔时间内，只容许发送1次报警
        Cache<String, String> cache = CacheBuilder.newBuilder().expireAfterWrite(notifyItem.getInterval(), TimeUnit.SECONDS).build();
        ALARM_LIMITER.put(key, cache);
    }

    /** 将某个线程池的报警项类型存入到缓存中 */
    public static void putVal(String threadPoolName, String type) {
        String key = genKey(threadPoolName, type);
        ALARM_LIMITER.get(key).put(type, type);
    }

    /** 获得某个线程池的报警项类型的报警限制信息 */
    public static String getAlarmLimitInfo(String key, String type) {
        return ALARM_LIMITER.get(key).getIfPresent(type);
    }

    /** 判断某个线程池的报警项类型，是否可以报警 */
    public static boolean ifAlarm(String threadPoolName, String type) {
        String key = genKey(threadPoolName, type);
        return StringUtils.isBlank(getAlarmLimitInfo(key, type)); // 如果【报警限制缓存】中不存在，返回true
    }

    public static String genKey(String threadPoolName, String type) {return threadPoolName + ":" + type;}
}
